namespace DCHealthCheck.DomainModel {

    #region Usings
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Objects.DataClasses;
    using System.Diagnostics;
    using System.Text; 
    #endregion

    [Table("DomainController")]
    public class DomainController : IDomainController, IObjectWithState, IValidatableObject {

        #region Members
        #region Max Length fields
        public static readonly int DNMaxLength = 900;
        public static readonly int SamAccountNameMaxLength = 20;
        public static readonly int DNSNameMaxLength = 255;
        public static readonly int DNSDomainMaxLength = 255;
        public static readonly int NetbiosDomainMaxLength = 15;
        public static readonly int ADSiteMaxLength = 255;
        public static readonly int OSNameMaxLength = 255;
        public static readonly int OSVersionMaxLength = 255;
        #endregion

        public virtual string ADSite { get; set; }

        public virtual string DN { get; set; }

        public virtual string DNSName { get; set; }

        public virtual string DNSDomain { get; set; }

        [Key]
        public virtual Guid Id { get; set; }

        public virtual string NetbiosDomain { get; set; }

        public virtual string OSName { get; set; }

        public virtual string OSVersion { get; set; }

        [Timestamp]
        public virtual byte[] RowVersion { get; set; }

        public virtual string SamAccountName { get; set; }

        public virtual DateTime WhenCreated { get; set; }

        #region Related Entities
        public virtual ICollection<SystemInfo> SystemInfos {
            get {
                if (systemInfos == null) systemInfos = new List<SystemInfo>();
                return systemInfos;
            }
            set { systemInfos = value; }
        }
        private ICollection<SystemInfo> systemInfos;
        #endregion

        #region NotMapped properties
        [NotMapped]
        public DetachedState DetachedState { get; set; }

        [NotMapped]
        public Object EntityKey { get { return this.Id; } }

        [Display(Name = "Name")]
        [NotMapped]
        public string SamAccountNameFriendly {
            get {
                if (this.SamAccountName != null) {
                    return this.SamAccountName.Replace("$", string.Empty);
                }
                else {
                    return string.Empty;
                }
            }
        }

        [NotMapped]
        public Dictionary<string, object> StartingOriginalValues { get; set; }
        #endregion 
        #endregion

        #region Constructor
        public DomainController() {
        } 
        #endregion

        #region Methods
        [DebuggerStepThroughAttribute]
        public override string ToString() {
            var info = new StringBuilder();
            info.Append("DomainController: ");
            info.AppendFormat("{0}", this.SamAccountNameFriendly != null ? this.SamAccountNameFriendly : "NULL");

            return info.ToString();
        }
        public string ToVerboseString() {
            var info = new StringBuilder();

            info.AppendFormat("Id: {0}; ", this.Id.ToString());
            info.AppendFormat("ADSite: {0}; ", this.ADSite);
            info.AppendFormat("DN: {0}; ", this.DN != null ? this.DN : "NULL");
            info.AppendFormat("DNSDomain: {0}; ", this.DNSDomain != null ? this.DNSDomain : "NULL");
            info.AppendFormat("DNSName: {0}; ", this.DNSName != null ? this.DNSName : "NULL");
            info.AppendFormat("NetbiosDomain: {0}; ", this.NetbiosDomain != null ? this.NetbiosDomain : "NULL");
            info.AppendFormat("OSName: {0}; ", this.OSName != null ? this.OSName : "NULL");
            info.AppendFormat("OSVersion: {0}; ", this.OSVersion != null ? this.OSVersion : "NULL");
            info.AppendFormat("SamAccountName: {0}; ", this.SamAccountName != null ? this.SamAccountName : "NULL");
            info.AppendFormat("WhenCreated: {0}", this.WhenCreated.ToString("yyyy-MMM-dd HH:mm:ss"));

            return info.ToString();
        }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
            if (this.Id == Guid.Empty) {
                yield return new ValidationResult(
                    "Id is required.  This should be the ObjectGuid attribute for the domain controller.", new[] { "Id" });
            }

            if (this.DetachedState != DetachedState.Deleted) {
                if (string.IsNullOrWhiteSpace(this.ADSite)) {
                    yield return new ValidationResult(
                        "ADSite is required.", new[] { "ADSite" });
                }
                else if (this.ADSite.Length > ADSiteMaxLength) {
                    yield return new ValidationResult(string.Format("ADSite length: {0} exceeds max length: {1}",
                        this.ADSite.Length, ADSiteMaxLength), new[] { "ADSite" });
                }

                if (string.IsNullOrWhiteSpace(this.DN)) {
                    yield return new ValidationResult(
                        "DN is required.  This should be the distinguished name of the domain controller.", new[] { "DN" });
                }
                else {
                    if ((this.DN.IndexOf(@",DC=", StringComparison.CurrentCultureIgnoreCase) == -1) ||
                        (this.DN.IndexOf(@"CN=", StringComparison.CurrentCultureIgnoreCase) == -1)) {
                        yield return new ValidationResult("DN format invalid LDAP syntax.", new[] { "DN" });
                    }

                    if (this.DN.Length > DNMaxLength) {
                        yield return new ValidationResult(string.Format("DN length: {0} exceeds max length: {1}",
                            this.DN.Length, DNMaxLength), new[] { "DN" });
                    }
                }

                if (string.IsNullOrWhiteSpace(this.DNSDomain)) {
                    yield return new ValidationResult(
                        "DNSDomain is required.", new[] { "DNSDomain" });
                }
                else if (this.DNSDomain.Length > DNSDomainMaxLength) {
                    yield return new ValidationResult(string.Format("DNSDomain length: {0} exceeds max length: {1}",
                        this.DNSDomain.Length, DNSDomainMaxLength), new[] { "DNSDomain" });
                }

                if (string.IsNullOrWhiteSpace(this.NetbiosDomain)) {
                    yield return new ValidationResult(
                        "NetbiosDomain is required.", new[] { "NetbiosDomain" });
                }
                else if (this.NetbiosDomain.Length > NetbiosDomainMaxLength) {
                    yield return new ValidationResult(string.Format("NetbiosDomain length: {0} exceeds max length: {1}",
                        this.NetbiosDomain.Length, NetbiosDomainMaxLength), new[] { "NetbiosDomain" });
                }

                if (string.IsNullOrWhiteSpace(this.OSName)) {
                    yield return new ValidationResult(
                        "OSName is required.", new[] { "OSName" });
                }
                else if (this.OSName.Length > OSNameMaxLength) {
                    yield return new ValidationResult(string.Format("OSName length: {0} exceeds max length: {1}",
                        this.OSName.Length, OSNameMaxLength), new[] { "OSName" });
                }

                if (string.IsNullOrWhiteSpace(this.OSVersion)) {
                    yield return new ValidationResult(
                        "OSVersion is required.", new[] { "OSVersion" });
                }
                else if (this.OSVersion.Length > OSVersionMaxLength) {
                    yield return new ValidationResult(string.Format("OSVersion length: {0} exceeds max length: {1}",
                        this.OSVersion.Length, OSVersionMaxLength), new[] { "OSVersion" });
                }

                if (string.IsNullOrWhiteSpace(this.SamAccountName)) {
                    yield return new ValidationResult(
                        "SamAccountName is required.", new[] { "SamAccountName" });
                }
                else if (this.SamAccountName.Length > SamAccountNameMaxLength) {
                    yield return new ValidationResult(string.Format("SamAccountName length: {0} exceeds max length: {1}",
                        this.SamAccountName.Length, SamAccountNameMaxLength), new[] { "SamAccountName" });
                }
            } // if (this.DetachedState != State.Deleted)
        }  
        #endregion
    }
}
